from rest_framework import serializers
from .models import User
import re
from django_redis import get_redis_connection
from rest_framework_jwt.settings import api_settings

class UserRegisterSerializer(serializers.Serializer):
    # 不使用ModelSerializer的原因：
    # 1.多个参数并不存在于模型类的属性中
    # 2.创建对象时需要将密码加密，但是封装的create方法并没有做这件事
    # 当前是注册逻辑，只考虑反序列化，不需要考虑序列化

    # 输出jwt,不接收客户端输入，只从服务器输出
    token=serializers.CharField(read_only=True)
    username=serializers.CharField(
        max_length=20,
        min_length=5,
        error_messages={
            'max_length':'请输入5-20个字符的用户名',
            'min_length':'请输入5-20个字符的用户名'
    },
    )
    password=serializers.CharField(
        min_length=8,
        max_length=20,
        error_messages={
            'min_length':'密码最少8位，最长20位',
            'max_length':'密码最少8位，最长20位'
        },write_only=True
    )

    password2=serializers.CharField(write_only=True)

    sms_code=serializers.IntegerField(write_only=True)

    mobile=serializers.CharField()

    allow=serializers.BooleanField(write_only=True)

    def validate_username(self,value):
        if User.objects.filter(username=value).count()>0:
            raise serializers.ValidationError('用户名已经存在')
        return value

    def validate_mobile(self,value):
        # 验证手机号格式是否正确
        if not re.match(r'^1[3-9]\d{9}$',value):
            raise serializers.ValidationError('手机号格式错误')
        # 判断手机号是否已经被使用
        if User.objects.filter(mobile=value).count()>0:
            raise serializers.ValidationError('手机号已经被使用')
        return value

    def validate_allow(self,value):
        if not value:
            raise serializers.ValidationError('必须同意协议')
        return value


    def validate(self, attrs):
        # 验证两个密码是否一致
        password1=attrs.get('password')
        password2=attrs.get('password2')
        if password1 !=password2:
            raise serializers.ValidationError('两个密码不一致')

        # 判断短信验证码是否正确
        mobile=attrs.get('mobile')
        sms_code=attrs.get('sms_code')
        redis_cli=get_redis_connection('sms')
        # 1.从redis中读取，sms_mobile
        sms_code_redis=redis_cli.get('sms_'+mobile)
        # 2.判断是否过期
        if sms_code_redis is None:
            raise serializers.ValidationError('短信验证码已过期')
        # 3.判断两个验证码是否一样
        if sms_code!=int(sms_code_redis):
            raise serializers.ValidationError('短信验证码错误')

        return attrs

    def create(self, validated_data):
        # validate_data 满足验证的请求数据
        # 1.从字典中获取数据
        username=validated_data.get('username')
        password=validated_data.get('password')
        mobile=validated_data.get('mobile')
        # 2.创建对象并保存
        user=User()
        user.username=username
        # 直接保存密码，未加密
        # user.password=password
        # 通过阅读官方文档知道这个方法，可以对密码加密后再保存到属性上
        user.set_password(password)
        user.mobile=mobile
        user.save()

        # 状态保持
        # 获取jwt方法
        jwt_payload_handler=api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler=api_settings.JWT_ENCODE_HANDLER
        # 2.生成载荷
        payload=jwt_payload_handler(user)
        # 3.生成口令
        token=jwt_encode_handler(payload)
        # 将口令添加到user对象上
        user.token=token

        return user

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields=['id','username','mobile','email','email_active']